package com.runfast.pay.service.impl;

import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.runfast.common.web.entity.Result;
import com.runfast.common.web.entity.ResultCode;
import com.runfast.paotui.dao.model.*;
import com.runfast.paotui.service.OrderService;
import com.runfast.paotui.service.OrderStatusHistoryService;
import com.runfast.paotui.service.RefundService;
import com.runfast.pay.Channel;
import com.runfast.pay.alipay.AlipayConfig;
import com.runfast.pay.service.AlipayService;
import com.runfast.pay.service.PayService;
import com.runfast.pay.service.WxpayService;
import com.runfast.pay.wxpay.WXPay;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.crypto.cipher.CryptoCipher;
import org.apache.commons.crypto.cipher.CryptoCipherFactory;
import org.apache.commons.crypto.utils.Utils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.crypto.spec.SecretKeySpec;
import java.text.ParseException;
import java.util.*;

import static javax.crypto.Cipher.DECRYPT_MODE;


/**
 * @author: lijin
 * @date: 2018年03月30日
 */

@Service
public class PayServiceImpl implements PayService {
    @Resource
    private WXPay wxAppPay;

    @Resource
    private WXPay wxPublicPay;

    @Autowired
    private AlipayService alipayService;

    @Autowired
    private WxpayService wxpayService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RefundService refundService;

    @Autowired
    private OrderStatusHistoryService orderStatusHistoryService;


    private String alipayPayNotifyUrl = "http://www.gxptkc.com";

    private String wxpayPayNotifyUrl = "http://www.gxptkc.com";

    private String wxpayRefundNotifyUrl = "http://www.gxptkc.com";

    @Override
    public Result prepay(Channel channel, String orderNo, String clientIp) {
        Validate.notNull(channel, "channel 不能为null");
        Validate.notBlank(orderNo, "orderNo 不能为空");
        Validate.notBlank(clientIp, "clientIp 不能为空");

        OrderExample orderExample = new OrderExample();
        orderExample.createCriteria()
                .andOrderNoEqualTo(orderNo);

        List<Order> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        Order order = orders.get(0);

        Order.Status status = order.getStatus();
        if (status != Order.Status.CREATED) return Result.fail(ResultCode.PAY_STATUS_UNPAID, "只能对新下的订单进行支付");

        Integer amountPayable = order.getAmountPayable();
        String goodsDescription = order.getGoodsDescription();

        Order orderUpdate = new Order();
        orderUpdate.withId(order.getId())
                .withChannel(channel);
        orderService.updateByPrimaryKeySelective(orderUpdate);
        switch (channel) {
            case ALIPAY_APP:
                String prepay = alipayService.prepay(orderNo, amountPayable, goodsDescription, "QUICK_MSECURITY_PAY", "1d", alipayPayNotifyUrl);

                return Result.ok("预下单成功", prepay);
            case WXPAY_APP:
            case WXPAY_PUBLIC:

                Map<String, String> stringMap = wxpayService.prepay(channel, orderNo, "跑腿快车外卖款", amountPayable, clientIp, wxpayPayNotifyUrl);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_PREPAY_FAIL, stringMap.get("err_code_des"));


                    return Result.ok("预下单成功", stringMap.get("prepay_id"));
                } else {
                    return Result.fail(ResultCode.PAY_PREPAY_FAIL, stringMap.get("return_msg"));
                }
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }

    }

    @Override
    public Result applyRefund(String orderNo, String refundNo, Integer refundAmount) {
        Validate.notBlank(orderNo, "orderNo 不能为空");
        Validate.notBlank(refundNo, "refundNo 不能为空");
        Validate.notNull(refundAmount, "refundAmount 不能为空");

        OrderExample orderExample = new OrderExample();
        orderExample.createCriteria()
                .andOrderNoEqualTo(orderNo);

        List<Order> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        Order order = orders.get(0);
        Boolean paid = order.getPaid();
        if (paid != null && paid) return Result.fail(ResultCode.PAY_STATUS_UNPAID, "订单未支付，不能发起退款");
        Integer amountPaid = order.getAmountPaid();

        if (amountPaid <= refundAmount) throw new RuntimeException("refundAmount必须小于等于payAmount");

        Refund refund = new Refund();
        refund.withStatus(Refund.Status.PENDING)
                .withAmount(refundAmount)
                .withChargeOrderNo(refundNo)
                .withOrderNo(orderNo)
                .withOrderId(order.getId())
                .withCreateTime(new Date())
                .withUpdateTime(new Date());

        orderService.insertSelective(order);

        Channel channel = order.getChannel();
        switch (channel) {
            case ALIPAY_APP:

                AlipayTradeRefundResponse refundResponse = alipayService.applyRefund(orderNo, refundNo, refundAmount);

                if (!refundResponse.isSuccess()) {
                    Refund refundUpdated = new Refund();
                    refundUpdated.withId(refund.getId())
                            .withStatus(Refund.Status.FAIL)
                            .withFailureCode(refundResponse.getSubCode())
                            .withFailureMsg(refundResponse.getSubMsg());
                    refundService.updateByPrimaryKeySelective(refundUpdated);
                    return Result.fail(ResultCode.PAY_REFUND_FAIL, refundResponse.getSubMsg());
                } else {
                    Refund refundUpdated = new Refund();
                    refundUpdated.withId(refund.getId())
                            .withTransactionNo(refundResponse.getTradeNo());
                    refundService.updateByPrimaryKeySelective(refundUpdated);

                    return Result.ok("退款申请成功");
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
                Map<String, String> stringMap = wxpayService.applyRefund(channel, orderNo, refundNo, amountPaid, refundAmount, wxpayRefundNotifyUrl);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode)) {
                        Refund refundUpdated = new Refund();
                        refundUpdated.withId(refund.getId())
                                .withStatus(Refund.Status.FAIL)
                                .withFailureCode(stringMap.get("err_code"))
                                .withFailureMsg(stringMap.get("err_code_des"));
                        refundService.updateByPrimaryKeySelective(refundUpdated);

                        return Result.fail(ResultCode.PAY_REFUND_FAIL, stringMap.get("err_code_des"));
                    } else {
                        Refund refundUpdated = new Refund();
                        refundUpdated.withId(refund.getId())
                                .withTransactionNo(stringMap.get("transaction_id"));
                        refundService.updateByPrimaryKeySelective(refundUpdated);

                        return Result.ok("退款申请成功（退款有一定延时，用零钱支付的退款20分钟内到账，银行卡支付的退款3个工作日后）");
                    }
                } else {
                    Refund refundUpdated = new Refund();
                    refundUpdated.withId(refund.getId())
                            .withStatus(Refund.Status.FAIL)
                            .withFailureCode(stringMap.get(returnCode))
                            .withFailureMsg(stringMap.get("return_msg"));
                    refundService.updateByPrimaryKeySelective(refundUpdated);
                    return Result.fail(ResultCode.PAY_REFUND_FAIL, stringMap.get("return_msg"));
                }
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }
    }

    @Override
    public Result orderQuery(String orderNo) {
        Validate.notBlank(orderNo, "orderNo 不能为空");

        OrderExample orderExample = new OrderExample();
        orderExample.createCriteria()
                .andOrderNoEqualTo(orderNo);

        List<Order> orders = orderService.selectByExample(orderExample);
        if (orders.isEmpty()) return Result.fail(ResultCode.ORDER_NOT_EXIST);
        Order order = orders.get(0);

        Channel channel = order.getChannel();
        switch (channel) {
            case ALIPAY_APP:
                AlipayTradeQueryResponse queryResponse = alipayService.orderQuery(orderNo);

                if (!queryResponse.isSuccess())
                    return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, queryResponse.getSubMsg());
                else {
                    String tradeStatus = queryResponse.getTradeStatus();
/*                    交易状态：WAIT_BUYER_PAY（交易创建，等待买家付款）、TRADE_CLOSED（未付款交易超时关闭，或支付完成后全额退款）、TRADE_SUCCESS（交易支付成功）、TRADE_FINISHED（交易结束，不可退款）*/

                    String statusMsg = "";
                    switch (tradeStatus) {
                        case "WAIT_BUYER_PAY":
                            statusMsg = "交易创建，等待买家付款";
                            break;
                        case "TRADE_CLOSED":
                            statusMsg = "未付款交易超时关闭，或支付完成后全额退款";
                            break;
                        case "TRADE_SUCCESS":
                            statusMsg = "支付成功";
                            if (order.getStatus() == Order.Status.CREATED) {

                                Order orderUpdated = new Order();
                                orderUpdated.withId(order.getId())
                                        .withAmountPaid(order.getAmountPayable())
                                        .withPaid(true)
                                        .withTimePaid(queryResponse.getSendPayDate());

                                orderService.updateByPrimaryKeySelective(orderUpdated);

                                OrderStatusHistory orderStatusHistoryAdded = new OrderStatusHistory();
                                orderStatusHistoryAdded.withOrderId(order.getId())
                                        .withCreateTime(new Date())
                                        .withUpdateTime(new Date())
                                        .withStatus(Order.Status.PAID);
                                orderStatusHistoryService.insertSelective(orderStatusHistoryAdded);
                            }
                            break;
                        case "TRADE_FINISHED":
                            statusMsg = "交易结束，不可退款";
                            break;
                        default:
                            statusMsg = "未知的支付状态";
                    }
                    return Result.ok(statusMsg, tradeStatus);
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
                Map<String, String> stringMap = wxpayService.orderQuery(channel, orderNo);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, stringMap.get("err_code_des"));
                    else {
                        /*SUCCESS—支付成功

                        REFUND—转入退款

                        NOTPAY—未支付

                        CLOSED—已关闭

                        REVOKED—已撤销（刷卡支付）

                        USERPAYING--用户支付中

                        PAYERROR--支付失败(其他原因，如银行返回失败)

                        支付状态机请见下单API页面*/
                        String tradeState = stringMap.get("trade_state");
                        String statusMsg = "";
                        switch (tradeState) {
                            case "SUCCESS":
                                statusMsg = "支付成功";
                                if (order.getStatus() == Order.Status.CREATED) {
                                    String timeEnd = stringMap.get("time_end");
                                    Date timePaid = null;
                                    try {
                                        timePaid = DateUtils.parseDateStrictly(timeEnd, "yyyyMMddHHmmss");
                                    } catch (ParseException e) {
                                        throw new RuntimeException(e);
                                    }
                                    Order orderUpdated = new Order();
                                    orderUpdated.withId(order.getId())
                                            .withAmountPaid(order.getAmountPayable())
                                            .withPaid(true)
                                            .withTimePaid(timePaid);

                                    orderService.updateByPrimaryKeySelective(orderUpdated);

                                    OrderStatusHistory orderStatusHistoryAdded = new OrderStatusHistory();
                                    orderStatusHistoryAdded.withOrderId(order.getId())
                                            .withCreateTime(new Date())
                                            .withUpdateTime(new Date())
                                            .withStatus(Order.Status.PAID);
                                    orderStatusHistoryService.insertSelective(orderStatusHistoryAdded);
                                }
                                break;
                            case "REFUND":
                                statusMsg = "转入退款";
                                break;
                            case "NOTPAY":
                                statusMsg = "未支付";
                                break;
                            case "CLOSED":
                                statusMsg = "已关闭";
                                break;
                            case "REVOKED":
                                statusMsg = "已撤销（刷卡支付）";
                                break;
                            case "USERPAYING":
                                statusMsg = "用户支付中";
                                break;
                            case "PAYERROR":
                                statusMsg = "支付失败(其他原因，如银行返回失败)";
                                break;
                            default:
                                statusMsg = "未知的支付状态";
                        }
                        return Result.ok(statusMsg, tradeState);
                    }
                } else {
                    return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, stringMap.get("return_msg"));
                }
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }


    }


    @Override
    public Result refundQuery(String refundNo) {

        RefundExample refundExample = new RefundExample();
        refundExample.createCriteria().andChargeOrderNoEqualTo(refundNo);
        List<Refund> refunds = refundService.selectByExample(refundExample);
        if (refunds.isEmpty()) return Result.fail(ResultCode.PARAMETER_ERROR, "不存在refundNo 对应的退款记录");

        Refund refund = refunds.get(0);
        Integer orderId = refund.getOrderId();
        Order order = orderService.selectByPrimaryKey(orderId);
        Channel channel = order.getChannel();
        switch (channel) {
            case ALIPAY_APP:
                AlipayTradeFastpayRefundQueryResponse response = alipayService.refundQuery(refundNo);

                if (!response.isSuccess())
                    return Result.fail(ResultCode.PAY_REFUND_FAIL, response.getSubMsg());
                else {
                    String status = response.getRefundStatus();
                    /*REFUND_PROCESSING 退款处理中；REFUND_SUCCESS 退款处理成功；REFUND_FAIL 退款失败;*/

                    String statusMsg = "";
                    switch (status) {
                        case "REFUND_PROCESSING":
                            statusMsg = "退款处理中";
                            break;
                        case "REFUND_SUCCESS":
                            statusMsg = "退款处理成功";

                            break;
                        case "REFUND_FAIL":
                            statusMsg = "退款失败";
                            break;
                        default:
                            statusMsg = "未知的退款状态";
                    }
                    return Result.ok(statusMsg, status);
                }
            case WXPAY_APP:
            case WXPAY_PUBLIC:
                Map<String, String> stringMap = wxpayService.refundrQuery(channel, refundNo);

                String returnCode = stringMap.get("return_code");
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = stringMap.get("result_code");
                    if (!"SUCCESS".equals(resultCode))
                        return Result.fail(ResultCode.PAY_REFUND_FAIL, stringMap.get("err_code_des"));
                    else {
                        /*退款状态：

                        SUCCESS—退款成功

                        REFUNDCLOSE—退款关闭。

                        PROCESSING—退款处理中

                        CHANGE—退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往商户平台（pay.weixin.qq.com）-交易中心，手动处理此笔退款。$n为下标，从0开始编号。
*/
                        String status = stringMap.get("refund_status");
                        String statusMsg = "";
                        switch (status) {
                            case "SUCCESS":
                                statusMsg = "退款成功";
                                break;
                            case "REFUNDCLOSE":
                                statusMsg = "退款关闭";
                                break;
                            case "PROCESSING":
                                statusMsg = "退款处理中";
                                break;
                            case "CHANGE":
                                statusMsg = "退款异常，退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，可前往商户平台（pay.weixin.qq.com）-交易中心，手动处理此笔退款";
                                break;
                            default:
                                statusMsg = "未知的退款状态";
                        }
                        return Result.ok(statusMsg, status);
                    }
                } else {
                    return Result.fail(ResultCode.PAY_ORDER_QUERY_FAIL, stringMap.get("return_msg"));
                }
            default:
                return Result.fail(ResultCode.PAY_CHANNEL_NOT_SUPPORT);
        }


    }


    @Override
    public String handleAlipayNotify(Map<String, String> paramsNotify) {


        try {
            boolean signVerified = AlipaySignature.rsaCheckV1(paramsNotify, AlipayConfig.ali_public_key, AlipayConfig.input_charset);
            if (signVerified) {

                String outTradeNo = paramsNotify.get("out_trade_no");
                String totalAmount = paramsNotify.get("total_amount");
                String sellerId = paramsNotify.get("seller_id");
                String appId = paramsNotify.get("app_id");
                String tradeStatus = paramsNotify.get("trade_status");
                String gmtPayment = paramsNotify.get("gmt_payment");
                Date timePaid = null;
                try {

                    timePaid = DateUtils.parseDateStrictly(gmtPayment, "yyyy-MM-dd HH:mm:ss");
                } catch (ParseException e) {
                    e.printStackTrace();
                    return "failure";
                }

                OrderExample orderExample = new OrderExample();
                orderExample.createCriteria().andOrderNoEqualTo(outTradeNo);

                List<Order> orders = orderService.selectByExample(orderExample);
                if (!orders.isEmpty()) {
                    Order order = orders.get(0);
                    if (totalAmount.equals(order.getAmountPayable()) && sellerId.equals(AlipayConfig.partner) && appId.equals(AlipayConfig.aliPay_AppID)) {

                        /*WAIT_BUYER_PAY	交易创建，等待买家付款
                        TRADE_CLOSED	未付款交易超时关闭，或支付完成后全额退款
                        TRADE_SUCCESS	交易支付成功
                        TRADE_FINISHED	交易结束，不可退款*/
                        switch (tradeStatus) {
                            case "WAIT_BUYER_PAY":
                                break;
                            case "TRADE_CLOSED":
                                break;
                            case "TRADE_SUCCESS":
                            case "TRADE_FINISHED":
                                if (order.getStatus() == Order.Status.CREATED) {
                                    Order orderUpdated = new Order();
                                    orderUpdated.withId(order.getId())
                                            .withAmountPaid(order.getAmountPayable())
                                            .withPaid(true)
                                            .withTimePaid(timePaid);

                                    orderService.updateByPrimaryKeySelective(orderUpdated);

                                    OrderStatusHistory orderStatusHistoryAdded = new OrderStatusHistory();
                                    orderStatusHistoryAdded.withOrderId(order.getId())
                                            .withCreateTime(new Date())
                                            .withUpdateTime(new Date())
                                            .withStatus(Order.Status.PAID);
                                    orderStatusHistoryService.insertSelective(orderStatusHistoryAdded);
                                }
                                break;

                        }

                        return "success";
                    }
                }

            }

        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return "failure";
    }


    @Override
    public String handleWxpayNotify(String xmlNotify) {

        Map<String, String> notifyMap = null;
        try {
            notifyMap = wxAppPay.processResponseXml(xmlNotify);
        } catch (Exception e) {
            e.printStackTrace();
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }

        String returnCode = notifyMap.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
            String resultCode = notifyMap.get("result_code");
            if ("SUCCESS".equals(resultCode)) {
                boolean signatureValid = false;
                try {
                    signatureValid = wxAppPay.isResponseSignatureValid(notifyMap);
                } catch (Exception e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }
                if (!signatureValid) return "";
                String totalFee = notifyMap.get("total_fee");
                String tradeType = notifyMap.get("trade_type");
                String outTradeNo = notifyMap.get("out_trade_no");
                String timeEnd = notifyMap.get("time_end");
                Date timePaid = null;
                try {
                    timePaid = DateUtils.parseDateStrictly(timeEnd, "yyyyMMddHHmmss");
                } catch (ParseException e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }


                OrderExample orderExample = new OrderExample();
                orderExample.createCriteria().andOrderNoEqualTo(outTradeNo);
                List<Order> orders = orderService.selectByExample(orderExample);
                if (!orders.isEmpty()) {
                    Order order = orders.get(0);
                    if (order.getAmountPayable() == Integer.valueOf(totalFee)) {
                        Boolean paid = order.getPaid();
                        if (!paid) {

                            Order orderUpdated = new Order();
                            orderUpdated.withId(order.getId())
                                    .withPaid(true)
                                    .withTimePaid(timePaid)
                                    .withAmountPaid(order.getAmountPayable());

                            orderService.updateByPrimaryKeySelective(orderUpdated);

                            OrderStatusHistory orderStatusHistoryAdded = new OrderStatusHistory();
                            orderStatusHistoryAdded.withOrderId(order.getId())
                                    .withCreateTime(new Date())
                                    .withUpdateTime(new Date())
                                    .withStatus(Order.Status.PAID);
                            orderStatusHistoryService.insertSelective(orderStatusHistoryAdded);

                        }
                        return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";
                    }


                }
            }


        }

        return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
    }

    @Override
    public String handleWxpayRefundNotify(String xmlNotify) {


        Map<String, String> notifyMap = null;
        try {
            notifyMap = wxAppPay.processResponseXml(xmlNotify);
        } catch (Exception e) {
            e.printStackTrace();
            return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
        }

        String returnCode = notifyMap.get("return_code");
        if ("SUCCESS".equals(returnCode)) {
            String resultCode = notifyMap.get("result_code");
            if ("SUCCESS".equals(resultCode)) {
                byte[] reqInfosDecoded = Base64.decodeBase64(notifyMap.get("req_info"));

                String appid = notifyMap.get("appid");
                String appID = wxAppPay.getConfig().getAppID();
                String key = null;
                if (appID.equals(appid)) {
                    key = wxAppPay.getConfig().getKey();
                } else {
                    key = wxPublicPay.getConfig().getKey();
                }

                String keyMd5 = DigestUtils.md5Hex(wxAppPay.getConfig().getKey()).toLowerCase();
                SecretKeySpec keySpec = new SecretKeySpec(keyMd5.getBytes(), "AES");

                Properties properties = new Properties();
                properties.setProperty(CryptoCipherFactory.CLASSES_KEY, CryptoCipherFactory.CipherProvider.JCE.getClassName());
                //Creates a CryptoCipher instance with the transformation and properties.
                final String transform = "AES/ECB/PKCS7Padding";

                String notifyDecoded = null;
                try {
                    CryptoCipher decipher = Utils.getCipherInstance(transform, properties);
                    decipher.init(DECRYPT_MODE, keySpec, null);
                    byte[] decoded = new byte[reqInfosDecoded.length * 2];
                    int outLength = decipher.doFinal(reqInfosDecoded, 0, reqInfosDecoded.length, decoded, 0);
                    notifyDecoded = new String(Arrays.copyOf(decoded, outLength));
                } catch (Exception e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }

                Map<String, String> mapDecoded = null;
                try {
                    mapDecoded = wxAppPay.processResponseXml(notifyDecoded);
                } catch (Exception e) {
                    e.printStackTrace();
                    return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";
                }

                String refundStatus = mapDecoded.get("refund_status");
                if ("SUCCESS".equals(refundStatus)) {

                    String transactionId = mapDecoded.get("transaction_id");
                    String outTradeNo = mapDecoded.get("out_trade_no");
                    String outRefundNo = mapDecoded.get("out_refund_no");
                    String successTime = mapDecoded.get("success_time");
                    Integer refundFee = Integer.valueOf(mapDecoded.get("refund_fee"));

                    OrderExample orderExample = new OrderExample();
                    orderExample.createCriteria().andOrderNoEqualTo(outTradeNo);
                    List<Order> orders = orderService.selectByExample(orderExample);
                    if (!orders.isEmpty()) {
                        Order order = orders.get(0);
                        Integer amountRefunded = order.getAmountRefunded();
                        amountRefunded += refundFee;
                        Boolean paid = order.getPaid();
                        if (!paid) {

                            Order orderUpdated = new Order();
                            orderUpdated.withId(order.getId())
                                    .withRefunded(true)
                                    .withAmountRefunded(amountRefunded);
                            orderService.updateByPrimaryKeySelective(orderUpdated);


                            RefundExample refundExample = new RefundExample();
                            refundExample.createCriteria()
                                    .andChargeOrderNoEqualTo(outRefundNo);
                            List<Refund> refunds = refundService.selectByExample(refundExample);
                            if (!refunds.isEmpty()) {
                                Refund refund = refunds.get(0);

                                Refund refundUpdated = new Refund();
                                refundUpdated.withId(refund.getId())
                                        .withAmount(refundFee)
                                        .withUpdateTime(new Date())
                                        .withTransactionNo(transactionId)
                                        .withStatus(Refund.Status.SUCCESS)
                                        .withSucceed(true)
                                        .withTimeSucceed(new Date());

                                refundService.updateByPrimaryKeySelective(refundUpdated);
                            }


                        }
                    }
                } else {
                    String outRefundNo = mapDecoded.get("out_refund_no");


                    RefundExample refundExample = new RefundExample();
                    refundExample.createCriteria()
                            .andChargeOrderNoEqualTo(outRefundNo);
                    List<Refund> refunds = refundService.selectByExample(refundExample);
                    if (!refunds.isEmpty()) {
                        Refund refund = refunds.get(0);

                        Refund refundUpdated = new Refund();
                        refundUpdated.withId(refund.getId())
                                .withStatus(Refund.Status.FAIL)
                                .withSucceed(false)
                                .withFailureCode(refundStatus);


                        refundService.updateByPrimaryKeySelective(refundUpdated);

                    }
                }
                return "<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>";

            }

        }
        return "<xml><return_code><![CDATA[FAIL]]></return_code></xml>";

    }
}

